#pragma once
#include <iostream>
#include <assert.h>
#include <vector>
#include <algorithm>
using namespace std;


namespace clx
{
  

  template<class T>
  struct _list_node
  {
    T _val;
    _list_node<T>* _prev;
    _list_node<T>* _next;
    _list_node(T val = T());                    //_list_node 构造函数
  };

  template <class T, class Ref, class Ptr>
  struct _list_iterator
  {
    typedef _list_node<T> node;
    typedef _list_iterator<T, Ref, Ptr> self;
    node* _pnode;
    _list_iterator(node* pnode);
    Ref operator*() const;
    Ptr operator->() const;
    bool operator==(const self& s) const;
    bool operator!=(const self& s) const;
    self& operator++();
    self& operator++(int);
    self& operator--();
    self& operator--(int);
    
  };

  template<class T>
  class list 
  {
    typedef _list_node<T> node;
    public:
    typedef _list_iterator<T, T&, T*> iterator;
    typedef _list_iterator<T, const T&, const T*> const_iterator;
      //iterator
      iterator begin();
      iterator end();
      const_iterator begin() const ;
      const_iterator end() const;

      //default member function
      list();                                   //list 构造函数
      list(const list<T>& lt);
      list<T>& operator=(list<T> lt);
      ~list();
      
      //modifiers
      void insert(iterator pos, const T& val);
      void push_back(const T& val);
      void push_front(const T& val);
      iterator erase(iterator pos);
      void pop_back();
      void pop_front();
      void clear();
      void swap(list<T>& lt);

      //capacity
      size_t size() const;
      bool empty() const;
      void print_list() const;

    private:
      node* _head;
  };
  void list_test()
  {
    list<int> lt1;
    lt1.push_back(1);
    lt1.push_back(2);
    lt1.push_back(3);
    lt1.push_back(4);
    lt1.print_list();
    cout << lt1.size() <<endl;
    list<int> lt2(lt1);
    lt2.print_list();
    lt2.clear();
    lt2.push_back(1);
    lt2.print_list();
    
    
  }
}


template<class T>
clx::_list_node<T>::_list_node(T val)                                   //_list_node 构造函数
      :_val(val)
      ,_prev(nullptr)
      ,_next(nullptr)
{}

template<class T, class Ref, class Ptr>
clx::_list_iterator<T, Ref, Ptr>::_list_iterator(node* pnode)          //_list_iterator 构造函数
  :_pnode(pnode)
{}


template<class T, class Ref, class Ptr>
Ref clx::_list_iterator<T, Ref, Ptr>::operator*() const
{
  return _pnode->_val;
}
template<class T, class Ref, class Ptr>
Ptr clx::_list_iterator<T, Ref, Ptr>::operator->() const
{
  return &_pnode->val;
}
template<class T, class Ref, class Ptr>
bool clx::_list_iterator<T, Ref, Ptr>::operator==(const self& s) const
{
  return _pnode == s._pnode;
}
template<class T, class Ref, class Ptr>
bool clx::_list_iterator<T, Ref, Ptr>::operator!=(const self& s) const
{
  return _pnode != s._pnode;
}
template<class T, class Ref, class Ptr>
typename clx::_list_iterator<T, Ref, Ptr>::self& clx::_list_iterator<T, Ref, Ptr>::operator++()
{
  _pnode = _pnode->_next;
  return *this;
}
template<class T, class Ref, class Ptr>
typename clx::_list_iterator<T, Ref, Ptr>::self& clx::_list_iterator<T, Ref, Ptr>::operator++(int)
{
  self tmp(*this);
  _pnode = _pnode->_next;
}
template<class T, class Ref, class Ptr>
typename clx::_list_iterator<T, Ref, Ptr>::self& clx::_list_iterator<T, Ref, Ptr>::operator--()
{
  _pnode = _pnode->_prev;
  return *this;
}
template<class T, class Ref, class Ptr>
typename clx::_list_iterator<T, Ref, Ptr>::self& clx::_list_iterator<T, Ref, Ptr>::operator--(int)
{
  self tmp(*this);
  _pnode = _pnode ->_prev;
}

template<class T>
typename clx::list<T>::iterator clx::list<T>::begin()
{
  return iterator(_head->_next);
}
template<class T>
typename clx::list<T>::iterator clx::list<T>::end()
{
  return iterator(_head);
}
template<class T>
typename clx::list<T>::const_iterator clx::list<T>::begin() const
{
  return const_iterator(_head->_next);
}
template<class T>
typename clx::list<T>::const_iterator clx::list<T>::end() const
{
  return const_iterator(_head);
}



template<class T>
clx::list<T>::list()                                                   //list 构造函数
   {
     _head = new node;
     _head->_prev = _head;
     _head->_next = _head;
   }

template<class T>
clx::list<T>::list(const list<T>& lt)
{
  _head = new node;
  _head->_prev = _head;
  _head->_next = _head;
  for (const auto& e : lt)
  {
    push_back(e);
  }
}

template<class T>
clx::list<T>& clx::list<T>::operator=(list<T> lt)
{
  swap(lt);
}

template<class T>
clx::list<T>::~list()
{
  iterator it = begin();
  while (it != end())
  {
    it = erase(it);
  }
}

template<class T>
void clx::list<T>::insert(iterator pos, const T& val)
{
  assert(pos._pnode);
  node* cur = pos._pnode;
  node* prev = cur->_prev;
  node* newnode = new node;
  // prev newnode cur
  prev->_next = newnode;
  newnode->_next = cur;
  cur->_prev = newnode;
  newnode->_prev = prev;
  newnode->_val = val;
}
template<class T>
void  clx::list<T>::push_back(const T& val)
{
  insert(end(), val);
}
template<class T>
void clx::list<T>::push_front(const T& val)
{
  insert(begin(), val);
}
template<class T>
typename clx::list<T>::iterator clx::list<T>::erase(iterator pos)
{
  node* prev = pos._pnode->_prev;
  node* next = pos._pnode->_next;
  // prev pos next
  prev->_next = next;
  next->_prev = prev;
  delete pos._pnode;
  return iterator(next);
}
template<class T>
void clx::list<T>::pop_back()
{
  erase(--end());
}
template<class T>
void clx::list<T>::pop_front()
{
  erase(begin());
}
template<class T>
void clx::list<T>::clear()
{
  iterator it = begin();
  while (it != end())
  {
    it = erase(it);
  }
}

template<class T>
void clx::list<T>::swap(list<T>& lt)
{
  ::swap(_head, lt._head);
}

template<class T>
bool clx::list<T>::empty() const
{
  return begin() == end();
}

template<class T>
size_t clx::list<T>::size() const
{
  size_t count = 0;
  const_iterator it = begin();
  while (it != end())
  {
    count++;
    it++;
  }
  return count;
}

template<class T>
void clx::list<T>::print_list() const
{
  const_iterator it = begin();
  while (it != end())
  {
    cout << *it << " ";
    it++;
  }
  cout << endl;
}












